// Frac.h
#ifndef FRAC_H
#define FRAC_H

#include <iostream>
#include <numeric>
#include <sstream>
#include <string>

class Frac {
public:
    Frac(int n = 0, int d = 1)
        : num(n)
        , den(d)
    {
        simplify();
    }

    // 加法
    Frac operator+(const Frac& rhs) const
    {
        return Frac(num * rhs.den + rhs.num * den, den * rhs.den);
    }

    // 减法
    Frac operator-(const Frac& rhs) const
    {
        return Frac(num * rhs.den - rhs.num * den, den * rhs.den);
    }

    // 乘法
    Frac operator*(const Frac& rhs) const
    {
        return Frac(num * rhs.num, den * rhs.den);
    }

    // 除法
    Frac operator/(const Frac& rhs) const
    {
        return Frac(num * rhs.den, den * rhs.num);
    }

    // 输出
    friend std::ostream& operator<<(std::ostream& os, const Frac& f)
    {
        if (f.den == 1){
            os << f.num;
            return os;
        }
        os << "\\frac{" << f.num << "}{" << f.den << "}";
        return os;
    }

    std::string to_string() const
    {
        std::ostringstream oss;
        oss << *this;
        return oss.str();
    }

    bool isZero() const { return num == 0; }
    bool isOne() const { return num == den; }
    bool isMinusOne() const { return num == -den; }
    int sign() const { return (num > 0) - (num < 0); }
    Frac abs() const { return Frac(std::abs(num), den); }

private:
    int num, den;

    // 约分
    void simplify()
    {
        if (den < 0) {
            num = -num;
            den = -den;
        }
        int g = std::gcd(num, den);
        if (g) {
            num /= g;
            den /= g;
        }
    }
};

#endif